package com.example.neuronview

import kotlin.math.sqrt
import java.io.BufferedReader
import java.io.FileReader
import java.io.IOException

/**
 * 表示SWC文件中的一个点
 */
class Point(point: List<Float>) {
    var parentIndex: Int = -1
    val children: MutableList<Point> = mutableListOf()
    var parent: Point? = null
    val index: Int = point[0].toInt()
    val type: Int = point[1].toInt()
    val x: Float = point[2]
    val y: Float = point[3]
    val z: Float = point[4]
    val ratio: Float = point[5]
    val xyz: List<Float> = listOf(point[2], point[3], point[4])

    init {
        parentIndex = point[6].toInt()
    }

    override fun toString(): String {
        return "$index,$type,$x,$y,$z,$ratio,$parentIndex"
    }
}

/**
 * 表示神经树中的一条边
 */
class Edge(point: Point? = null) {
    val data: MutableList<Point> = if (point != null) mutableListOf(point) else mutableListOf()
    var order: Int = -1
    var angle: Double = 0.0
    var maxDepth: Int = -1
    var maxLength: Double = -1.0
    val children: MutableList<Edge> = mutableListOf()
    var parent: Edge? = null
    var len: Double = 0.0

    fun addPoint(point: Point) {
        data.add(point)
    }

    fun getLength(): Double {
        if (len == 0.0) {
            for (i in 0 until data.size - 1) {
                len += calculateDistance(data[i].xyz, data[i + 1].xyz)
            }
        }
        return len
    }

    private fun calculateDistance(p1: List<Float>, p2: List<Float>): Double {
        val dx = p1[0] - p2[0]
        val dy = p1[1] - p2[1]
        val dz = p1[2] - p2[2]
        return sqrt((dx * dx + dy * dy + dz * dz).toDouble())
    }
}

/**
 * 表示完整的神经树结构
 */
class NeuronTree {
    var root: Point? = null
    val edges: MutableList<Edge> = mutableListOf()
    val points: MutableList<Point> = mutableListOf()
    var width: Int = 1
    val branchs: MutableList<Any> = mutableListOf() // 原代码未使用，保留空列表
    val terminals: MutableList<Point> = mutableListOf()
    val swc: MutableMap<Int, Point> = mutableMapOf()
    val xyz: MutableList<List<Float>> = mutableListOf()
    var somaRadius: Int = 200
    var somaHide: Boolean = false
    var axonHide: Boolean = false
    var dendriteHide: Boolean = false
    var maxOrder: Int = -1
    var rootAxonEdge: Edge? = null
    val dendrites: MutableList<Edge> = mutableListOf()

    /** 从SWC格式字符串读取数据 */
    fun readSWC(swc: String):Geometry {
        swc.lines().forEach { line ->
            if (line.isNotBlank() && !line.startsWith('#') && !line.startsWith('\r')) {
                val p = line.split("\\s+".toRegex()).map { it.toFloat() }
                this.swc[p[0].toInt()] = Point(p)
            }
        }
        val geometry = parseswc()
        return geometry
    }

    /** 从文件读取SWC数据 */
    fun readFile(filename: String = "", spliter: String = " "): Geometry {
        try {
            BufferedReader(FileReader(filename)).use { reader ->
                reader.lineSequence().forEach { line ->
                    if (line.isNotBlank() && !line.startsWith('#')) {
                        val p = line.split(spliter).map { it.toFloat() }
                        this.swc[p[0].toInt()] = Point(p)
                    }
                }
            }
        } catch (e: IOException) {
            println("Error reading file: $filename")
            e.printStackTrace()
        }
        val geometry = parseswc()
        return geometry
    }

    /** 解析SWC数据，构建树结构 */
    fun parseswc():Geometry {
        swc.forEach { (_, point) ->
            xyz.add(point.xyz)
            points.add(point)
            if (point.parentIndex == -1 && root == null) {
                root = point
            }
        }
        getEdges()

        edges.forEach { edge ->
            if (rootAxonEdge == null &&
                (edge.data[0] == root || edge.data[0].type == 3) &&
                (edge.data[1].type != 3)) {
                rootAxonEdge = edge
            }
            if (edge.data.last().children.isEmpty()) {
                terminals.add(edge.data.last())
            }
        }

        edges.forEach { edge ->
            val tail = edge.data.last()
            tail.children.forEach { child ->
                edges.forEach { edge0 ->
                    if (child == edge0.data[1]) {
                        edge.children.add(edge0)
                        edge0.parent = edge
                    }
                }
            }
        }
        val geometry= Geometry()
        val vertex = Vertex()
        val position: PropertyType<Float> =PropertyType<Float>()
        vertex.addProperties(Type.Vertex,position)
        geometry.setVertex(vertex)
        val step=20
        edges.forEach { edge ->
            var edgestart =0
            var tempList=mutableListOf<Point>()
            for (i in 0 until edge.data.size step step){
                val point =edge.data[i]
                tempList.add(point)
            }
            tempList.add(edge.data.last())
            tempList.forEach { point ->
                if (edgestart>0)
                {
                    val point0 = tempList[edgestart-1]
                    position.run {
                        addItem(point0.x/10000)
                        addItem(point0.y/10000)
                        addItem(point0.z/10000)
                    }
                    position.run {
                        addItem(point.x/10000)
                        addItem(point.y/10000)
                        addItem(point.z/10000)
                    }
                }
                edgestart+=1
            }

//            edge.data.forEach { point ->
//                if (edgestart>0)
//                {
//                    val point0 = edge.data[edgestart-1]
//                    position.run {
//                        addItem(point0.x/10000)
//                        addItem(point0.y/10000)
//                        addItem(point0.z/10000)
//                    }
//                    position.run {
//                        addItem(point.x/10000)
//                        addItem(point.y/10000)
//                        addItem(point.z/10000)
//                    }
//                }
//                edgestart+=1
//            }
        }
        return geometry
    }

    /** 获取树突边列表 */
    fun getDendrite(): List<Edge> {
        if (dendrites.isEmpty()) {
            edges.forEach { edge ->
                if (edge.data[1].type == 3) {
                    dendrites.add(edge)
                }
            }
        }
        return dendrites
    }

    /** 构建边结构 */
    fun getEdges() {
        swc.forEach { (_, point) ->
            if (point.parentIndex != -1 && swc.containsKey(point.parentIndex)) {
                point.parent = swc[point.parentIndex]
                point.parent?.children?.add(point)
            }
        }

        val start = swc[swc.keys.first()] ?: return
        if (start.children.isNotEmpty()) {
            getEdge(start)
        }
    }

    /** 递归构建边 */
    private fun getEdge(start: Point) {
        start.children.forEach { p ->
            val edge = Edge(start)
            var edgestart = p

            while (edgestart.children.size == 1) {
                edge.addPoint(edgestart)
                edgestart = edgestart.children[0]
            }

            edge.addPoint(edgestart)
            edges.add(edge)
            getEdge(edgestart)
        }
    }
}